﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Web.Mvc;
using System.Web.Routing;
using System.Web.Security;

namespace Utilities
{
    public class Utility
    {
        private static readonly byte[] bytes = Encoding.ASCII.GetBytes("Sovigaz1");

        public static CultureInfo Info;

        public static int UserID
        {
            get
            {
                int userID = 0;
                string value = CookieHelper.GetCookieValue(FormsAuthentication.FormsCookieName);
                if (!String.IsNullOrWhiteSpace(value))
                {
                    try
                    {
                        var authTicket = FormsAuthentication.Decrypt(value);
                        if (authTicket != null) userID = ConvertUtility.IntParse(authTicket.UserData.Split(';')[0]);
                    }
                    catch
                    {
                        return userID;
                    }
                }
                return userID;
            }
        }

        public static string Username
        {
            get
            {
                string username = String.Empty;
                string value = CookieHelper.GetCookieValue(FormsAuthentication.FormsCookieName);
                if (!String.IsNullOrWhiteSpace(value))
                {
                    try
                    {
                        var authTicket = FormsAuthentication.Decrypt(value);
                        if (authTicket != null) username = ConvertUtility.StringParse(authTicket.UserData.Split(';')[1]);
                    }
                    catch
                    {
                        return username;
                    }
                }
                return username;
            }
        }

        public static string FullName
        {
            get
            {
                string username = String.Empty;
                string value = CookieHelper.GetCookieValue(FormsAuthentication.FormsCookieName);
                if (!String.IsNullOrWhiteSpace(value))
                {
                    try
                    {
                        var authTicket = FormsAuthentication.Decrypt(value);
                        if (authTicket != null) username = ConvertUtility.StringParse(authTicket.UserData.Split(';')[2]);
                    }
                    catch
                    {
                        return username;
                    }
                }
                return username;
            }
        }

        public static bool ArrayEqual<T>(T[] a1, T[] a2)
        {
            if (ReferenceEquals(a1, a2))
                return true;

            if (a1 == null || a2 == null)
                return false;

            if (a1.Length != a2.Length)
                return false;

            EqualityComparer<T> comparer = EqualityComparer<T>.Default;
            return !a1.Where((t, i) => !comparer.Equals(t, a2[i])).Any();
        }

        public static string MD5Encrypt(string password)
        {
            var md5Hasher = new MD5CryptoServiceProvider();
            var encoder = new UTF8Encoding();
            var hashedBytes = md5Hasher.ComputeHash(encoder.GetBytes(password));

            return hashedBytes.Aggregate(String.Empty, (current, b) => current + b.ToString("x2"));
        }

        public static string Encrypt(string originalString)
        {
            if (String.IsNullOrWhiteSpace(originalString))
                return String.Empty;

            var cryptoProvider = new DESCryptoServiceProvider();
            var memoryStream = new MemoryStream();
            var cryptoStream = new CryptoStream(memoryStream,
                cryptoProvider.CreateEncryptor(bytes, bytes), CryptoStreamMode.Write);
            var writer = new StreamWriter(cryptoStream);
            writer.Write(originalString);
            writer.Flush();
            cryptoStream.FlushFinalBlock();
            writer.Flush();

            return Convert.ToBase64String(memoryStream.GetBuffer(), 0, (int) memoryStream.Length);
        }

        public static string Decrypt(string cryptedString)
        {
            if (String.IsNullOrWhiteSpace(cryptedString))
                return String.Empty;

            var cryptoProvider = new DESCryptoServiceProvider();
            var memoryStream = new MemoryStream
                (Convert.FromBase64String(cryptedString));
            var cryptoStream = new CryptoStream(memoryStream,
                cryptoProvider.CreateDecryptor(bytes, bytes), CryptoStreamMode.Read);
            var reader = new StreamReader(cryptoStream);

            return reader.ReadToEnd();
        }

        public static void LogEx(string exCode, Exception ex)
        {
            string fileName = AppDomain.CurrentDomain.BaseDirectory + @"\Error.log";
            using (StreamWriter f = File.AppendText(fileName))
            {
                string Str = "----------------header------------------------\r\n";
                Str = Str + "Timestamp: " + DateTime.Now.ToString("y/MM/ddyyy - HH:mm");
                Str = Str + "\r\nExceptionCode: " + exCode;
                Str = Str + "\r\nMessage: " + ex.Message;
                Str = Str + "\r\nStackTrace:\r\n" + ex.StackTrace;
                Str = Str + "\r\nSource: " + ex.Source;
                Str = Str + "\r\n\r\n";

                f.Write(Str);
                f.Close();
            }
        }
    }

    public class LogAndRedirectOnErrorAttribute : FilterAttribute, IExceptionFilter
    {
        public void OnException(ExceptionContext filterContext)
        {
            //Do logging here
            Utility.LogEx("Exception", filterContext.Exception);

            filterContext.Controller.ViewBag.Error = "Có lỗi xảy ra.";

            //redirect to error handler
            filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(
                new
                {
                    controller = "Home",
                    action = "Error"
                }));

            // Stop any other exception handlers from running
            filterContext.ExceptionHandled = true;

            // CLear out anything already in the response
            filterContext.HttpContext.Response.Clear();
        }
    }

    public class AuthenticationAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            string controller = filterContext.Controller.ControllerContext.RouteData.Values["controller"].ToString();
            string action = filterContext.Controller.ControllerContext.RouteData.Values["action"].ToString();
            if (controller != "Account" && action != "Login" && action != "Logout")
            {
                int userID = Utility.UserID;
                if (userID == 0)
                {
                    filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(
                        new
                        {
                            controller = "Account",
                            action = "Login"
                        }));
                }
            }
            base.OnActionExecuting(filterContext);
        }
    }
}